use std::ffi::CStr;
use std::ffi::CString;
use std::ptr;
use std::os::raw::c_void;
use std::path::Path;
use ash::vk::CommandBufferUsageFlags;
use memoffset::offset_of;
use std::mem::size_of;

use ash::vk::BufferCreateFlags;
use ash::extensions::khr::Surface;
use ash::vk;
use ash::vk::BlendFactor;
use ash::vk::ColorComponentFlags;
use ash::vk::CommandPoolCreateFlags;
use ash::vk::Extent2D;
use ash::vk::FenceCreateFlags;
use ash::vk::Framebuffer;
use ash::vk::FramebufferCreateFlags;
use ash::vk::ImageSubresourceRange;
use ash::vk::ImageView;
use ash::vk::Offset2D;
use ash::vk::PipelineColorBlendStateCreateFlags;
use ash::vk::PipelineCreateFlags;
use ash::vk::PipelineDynamicStateCreateFlags;
use ash::vk::PipelineInputAssemblyStateCreateFlags;
use ash::vk::PipelineLayoutCreateFlags;
use ash::vk::PipelineMultisampleStateCreateFlags;
use ash::vk::PipelineRasterizationStateCreateFlags;
use ash::vk::PipelineShaderStageCreateFlags;
use ash::vk::PipelineVertexInputStateCreateFlags;
use ash::vk::PipelineViewportStateCreateFlags;
use ash::vk::PresentModeKHR;
use ash::vk::RenderPassCreateFlags;
use ash::vk::SemaphoreCreateFlags;
use ash::vk::ShaderModule;
use ash::vk::SurfaceFormatKHR;

use crate::utils::platform;
use crate::utils::constant::*;
use crate::utils::tools::vk_to_string;
pub use crate::vulkan::vulkan_rhi::*;

// 设置错误回调函数
unsafe extern "system" fn vulkan_debug_utils_callback(
    message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
    message_type: vk::DebugUtilsMessageTypeFlagsEXT,
    p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT,
    _p_user_data: *mut c_void
) -> vk::Bool32 {
    let severity_str = match message_severity {
        vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE => "Verbose",
        vk::DebugUtilsMessageSeverityFlagsEXT::INFO => "Info",
        vk::DebugUtilsMessageSeverityFlagsEXT::WARNING => "Warning",
        vk::DebugUtilsMessageSeverityFlagsEXT::ERROR => "Error",
        _ => {"None"}
    };

    let type_str = match message_type {
        vk::DebugUtilsMessageTypeFlagsEXT::DEVICE_ADDRESS_BINDING => "device_address_binding",
        vk::DebugUtilsMessageTypeFlagsEXT::GENERAL => "General",
        vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE => "Performace",
        vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION => "Validation",
        _ => {"None"}
    };

    eprintln!("validation layer: [{}][{}] {:?}", severity_str, type_str, CStr::from_ptr((*p_callback_data).p_message));

    vk::FALSE
}

impl VulkanRHI {
    pub fn create_instance(entry: &ash::Entry) -> ash::Instance {
        if ENABLE_VALIDATION && VulkanRHI::check_validation_layer_support(entry) == false {
            panic!("Failed to get validation layer support");
        }
        
        // 设置Application Info
        let app_name = CString::new(WINDOW_TITLE).unwrap();
        let engine_name = CString::new("Vulkan Engine").unwrap();
        let app_info = vk::ApplicationInfo {
            s_type: vk::StructureType::APPLICATION_INFO,
            // p_next: ptr::null(),
            p_application_name: app_name.as_ptr(),
            application_version: vk::make_api_version(0, 1, 0, 0),
            p_engine_name: engine_name.as_ptr(),
            engine_version: vk::make_api_version(0, 1, 0, 0),
            api_version: vk::make_api_version(0, 1, 3, 0),
            ..Default::default()
        };

        let extension_names = platform::required_extension_names();
        println!("{:?}", extension_names);

        // To Deep: 为什么不能合成一句
        let requred_validation_layer_raw_names: Vec<CString> = REQUIRED_VALIDATION_LAYERS
            .iter()
            .map(|layer_name| CString::new(*layer_name).unwrap())
            .collect();
        let enable_layer_names: Vec<*const i8> = requred_validation_layer_raw_names
            .iter()
            .map(|layer_name| layer_name.as_ptr())
            .collect();
                // let enable_layer_names: Vec<*const i8> = REQUIRED_VALIDATION_LAYERS
                //     .iter()
                //     .map(|layer_name| CString::new(*layer_name).unwrap().as_ptr())
                //     .collect();

        // 设置 Create Info
        let create_info = vk::InstanceCreateInfo {
            s_type: vk::StructureType::INSTANCE_CREATE_INFO,
            p_next: if ENABLE_VALIDATION { 
                &VulkanRHI::populate_debug_messenger_create_info() 
                    as *const vk::DebugUtilsMessengerCreateInfoEXT 
                    as *const c_void
            } else { 
                ptr::null()
            },
            flags: vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR,
            p_application_info: &app_info,
            enabled_layer_count: if ENABLE_VALIDATION { 
                enable_layer_names.len() as u32 
            } else { 
                0 
            }, // Ch.2
            pp_enabled_layer_names: if ENABLE_VALIDATION {
                // 不能放在这里，下面调用的时候是unsafe状态，然而括号结束的时候，已经被释放了
                // let requred_validation_layer_raw_names: Vec<CString> = REQUIRED_VALIDATION_LAYERS
                //     .iter()
                //     .map(|layer_name| CString::new(*layer_name).unwrap())
                //     .collect();
                // let enable_layer_names: Vec<*const i8> = requred_validation_layer_raw_names
                //     .iter()
                //     .map(|layer_name| layer_name.as_ptr())
                //     .collect();
                enable_layer_names.as_ptr()
            } else { 
                ptr::null()
            }, // Ch.2
            enabled_extension_count: extension_names.len() as u32,
            pp_enabled_extension_names: extension_names.as_ptr()
        };

        // unsafe 包围中创建
        let instance: ash::Instance = unsafe {
            entry
                .create_instance(&create_info, None)
                .expect("Failed to create instance!")
        };

        instance
    }

    // validation layer Ch.2
    pub fn check_validation_layer_support(entry: &ash::Entry) -> bool{
        // load info from entry
        let layer_properties = entry
            .enumerate_instance_layer_properties()
            .expect("Failed to Enumerate Instance Layer Properties");

        // check info state
        if layer_properties.len() <= 0 {
            eprintln!("No available layers.");
            return false;
        } else {
            println!("Instance Available Layers: ");
            for layer_property in layer_properties.iter() {
                let layer_property_name = vk_to_string(&layer_property.layer_name);
                println!("\t{}", layer_property_name);
            }
        }

        // check required_list with entry return
        for required_layer_name in REQUIRED_VALIDATION_LAYERS.iter() {
            let mut is_layer_found = false;

            for layer_property in layer_properties.iter() {
                let layer_property_name = vk_to_string(&layer_property.layer_name);

                if layer_property_name.eq(required_layer_name) {
                    is_layer_found = true;
                    break;
                }
            }
            // if not found
            if is_layer_found == false {
                return false;
            }
        }

        true
    }

    // messenger ch.2
    pub fn setup_debug_messenger(entry: &ash::Entry, instance: &ash::Instance) -> (ash::extensions::ext::DebugUtils, vk::DebugUtilsMessengerEXT) {
        let debug_utils = ash::extensions::ext::DebugUtils::new(&entry, &instance);

        if !ENABLE_VALIDATION {
            return (debug_utils, vk::DebugUtilsMessengerEXT::null())
        }
        let create_info = VulkanRHI::populate_debug_messenger_create_info();
        let debug_utils_messenger = unsafe{
            debug_utils.create_debug_utils_messenger(&create_info, None).expect("debug_utils create is None")
        };

        (debug_utils, debug_utils_messenger)
    }

    pub fn populate_debug_messenger_create_info() -> vk::DebugUtilsMessengerCreateInfoEXT {
        vk::DebugUtilsMessengerCreateInfoEXT {
            s_type : 
                vk::StructureType::DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
            // p_next :
            //     ptr::null(),
            // flags :
            //     vk::DebugUtilsMessengerCreateFlagsEXT::empty(),
            message_severity : 
                vk::DebugUtilsMessageSeverityFlagsEXT::ERROR |
                vk::DebugUtilsMessageSeverityFlagsEXT::WARNING | 
                vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE,
            message_type :
                vk::DebugUtilsMessageTypeFlagsEXT::GENERAL | 
                vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION | 
                vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE,
            pfn_user_callback :
                Some(vulkan_debug_utils_callback),
            p_user_data:
                ptr::null_mut(),
            ..Default::default()
        }
    }

    pub fn pick_physics_device(instance: &ash::Instance, surface_stuff: &SurfaceStuff) -> vk::PhysicalDevice {
        let physical_devices = unsafe {
            instance
                .enumerate_physical_devices()
                .expect("failed to find gpus with Vulkan support!")
        };
    
        let mut result = None;
        for &physical_device in physical_devices.iter() {
            if VulkanRHI::is_device_suitable(instance, physical_device, surface_stuff) {
                if result.is_none() {
                    result = Some(physical_device);
                }
            }
        }

        match result {
            None => panic!("failed to find a suitable GPU!"),
            Some(physical_device) => physical_device
        }
    }

    pub fn is_device_suitable(instance: &ash::Instance, physical_device: vk::PhysicalDevice, surface_stuff: &SurfaceStuff) -> bool {
        let device_properties = unsafe{
            instance.get_physical_device_properties(physical_device)
        };

        let mut subset_properties = vk::PhysicalDevicePortabilitySubsetPropertiesKHR::default().clone();
        let mut device_properties2 = vk::PhysicalDeviceProperties2 {
            s_type: vk::StructureType::PHYSICAL_DEVICE_PROPERTIES_2_KHR,
            p_next: &mut subset_properties
                as *mut vk::PhysicalDevicePortabilitySubsetPropertiesKHR 
                as *mut c_void,
            properties: device_properties
        };
        println!("{:?}", device_properties2);
        
        vk::PhysicalDeviceProperties2::builder();
        unsafe {
            instance.get_physical_device_properties2(physical_device, &mut device_properties2);
        };

        let device_features = unsafe {
            instance.get_physical_device_features(physical_device)
        };

        println!("[Device Properties2] {:?}", device_properties2.properties.limits);

        println!("[Device] {}", vk_to_string(&device_properties.device_name));

        // 检查Queue
        let queue_family_indices: QueueFamilyIndices = VulkanRHI::find_queue_family(instance, &physical_device, surface_stuff);
        // 检查SwapChain
        let extensions_supported = VulkanRHI::check_device_extensions_support(instance, &physical_device);
        // 检查SwapChainDetails
        let swapchain_adequate = match extensions_supported {
            true => {
                let swapchain_support_details = VulkanRHI::query_swapchain_support(surface_stuff, &physical_device);
                !swapchain_support_details.formats.is_empty() && !swapchain_support_details.present_modes.is_empty()
            },
            false => false
        };

        println!("{:?}", device_properties.device_type);
        println!("{:?}", device_features.geometry_shader);
        println!("{:?}", queue_family_indices.is_complete());
        println!("{:?}", extensions_supported);
        println!("{:?}", swapchain_adequate);
        println!("{:?}", device_features.sampler_anisotropy);

        //(
        //    device_properties.device_type == vk::PhysicalDeviceType::DISCRETE_GPU 
        //    && 
        //    device_features.geometry_shader != 0
        //) 
        //&&
        queue_family_indices.is_complete() && extensions_supported && swapchain_adequate && device_features.sampler_anisotropy != 0
    }

    // 查询对device extension的支持
    pub fn check_device_extensions_support(instance: &ash::Instance, physical_device: &vk::PhysicalDevice) -> bool {
        let device_extension_properties = unsafe {
            instance
                .enumerate_device_extension_properties(*physical_device)
                .expect("failed to load device extension properties!")
        };

        let mut is_full_supported = true;
        for required_device_extension in DEVICE_EXTENSIONS.iter() {
            if device_extension_properties.iter()
                .map( // [i8, 256]转换为String
                    |device_extension_property| 
                        // String::from_utf8((&device_extension_property.extension_name).iter().filter(|&c| c > &0).map(|&c| c as u8).collect()).unwrap())
                        vk_to_string(&device_extension_property.extension_name)
                ).filter( // 判断相等
                    |device_extension_property| {
                        println!("{:?}", device_extension_property);
                        device_extension_property == required_device_extension
                    }
                ).count() == 0 {
                is_full_supported = false;
                break;
            }
        }

        return is_full_supported
    }

    // 查询对Queue的支持程度
    pub fn find_queue_family(instance: &ash::Instance, physical_device: &vk::PhysicalDevice, surface_stuff: &SurfaceStuff) -> QueueFamilyIndices {
        let physical_device_queue_family_properties = unsafe { 
            instance
                .get_physical_device_queue_family_properties(*physical_device)
        };

        let mut queue_family_indices = QueueFamilyIndices {
            graphics_family: None,
            present_family: None
        };

        let mut i = 0;
        println!("Queue Families: Num({})", physical_device_queue_family_properties.len());
        for queue_family_property in physical_device_queue_family_properties.iter() {
            // 查看Surface支持
            let is_present_support = unsafe {
                surface_stuff.surface_loader.get_physical_device_surface_support(
                    *physical_device,
                    i,
                    surface_stuff.surface)
            };
            println!("\t Queue : flags({:?}), count({}), Surface_Support({})", queue_family_property.queue_flags, queue_family_property.queue_count, is_present_support.unwrap());
            i += 1;
        }

        let mut i = 0;
        for queue_family_property in physical_device_queue_family_properties.iter() {
            // 查看设备存在
            if queue_family_property.queue_count > 0 && queue_family_property.queue_flags.contains(vk::QueueFlags::GRAPHICS) {
                queue_family_indices.graphics_family = Some(i);
            }
            // 查看Surface支持
            let is_present_support = unsafe {
                surface_stuff.surface_loader.get_physical_device_surface_support(
                    *physical_device,
                    i,
                    surface_stuff.surface)
            };
            if queue_family_property.queue_count > 0 && is_present_support.unwrap_or(false) {
                queue_family_indices.present_family = Some(i);
            }
            // 如果都满足
            if queue_family_indices.is_complete() {
                break;
            }
            i += 1;
        }
        queue_family_indices
    }

    // 
    pub fn create_logic_device(instance: &ash::Instance, physical_device: vk::PhysicalDevice, surface_stuff: &SurfaceStuff) -> (ash::Device, vk::Queue, vk::Queue) {
        let queue_family_indices = VulkanRHI::find_queue_family(instance, &physical_device, surface_stuff);

        use std::collections::HashSet;
        let mut unique_queue_families = HashSet::new();
        unique_queue_families.insert(queue_family_indices.graphics_family.unwrap());
        unique_queue_families.insert(queue_family_indices.present_family.unwrap());

        // 初始化Queue Create Info
        let queue_priorities = 1.0f32;
        let mut device_queue_create_infos = vec![];
        for queue_family in unique_queue_families.iter() {
            device_queue_create_infos.push(
                vk::DeviceQueueCreateInfo {
                    s_type: vk::StructureType::DEVICE_QUEUE_CREATE_INFO,
                    p_next: ptr::null(),
                    flags: vk::DeviceQueueCreateFlags::empty(),
                    queue_family_index: *queue_family,
                    queue_count: 1,
                    p_queue_priorities: &queue_priorities,
                    ..Default::default()
                }
            );
        };

        let device_feature = vk::PhysicalDeviceFeatures {
            sampler_anisotropy: vk::TRUE,
            ..Default::default()
        };

        // Device extension, SwapChain
        let device_extensions_raw_names: Vec<CString> = DEVICE_EXTENSIONS
            .iter()
            .map(|layer_name| CString::new(*layer_name).unwrap())
            .collect();
        let device_extensions_names: Vec<*const i8> = device_extensions_raw_names
            .iter()
            .map(|layer_name| layer_name.as_ptr())
            .collect();

        let device_create_info = vk::DeviceCreateInfo { // Validation Layer似乎被废弃了
            s_type: vk::StructureType::DEVICE_CREATE_INFO,
            p_next: ptr::null(),
            p_queue_create_infos: device_queue_create_infos.as_ptr(),
            queue_create_info_count: device_queue_create_infos.len() as u32,
            p_enabled_features: &device_feature,
            enabled_extension_count: 
                DEVICE_EXTENSIONS.len() as u32,
            pp_enabled_extension_names:
                device_extensions_names.as_ptr(),
            ..Default::default()
        };

        let device = unsafe { 
            instance
                .create_device(physical_device, &device_create_info, None)
                .expect("failed to create logic device!")
        };

        let graphics_queue = unsafe {
            device.get_device_queue(queue_family_indices.graphics_family.unwrap(), 0)
        };
        let present_queue = unsafe {
            device.get_device_queue(queue_family_indices.present_family.unwrap(), 0)
        };

        (device, graphics_queue, present_queue)
    }

    // 创造surface
    pub fn create_surface(entry: &ash::Entry, instance: &ash::Instance, window: &winit::window::Window) -> SurfaceStuff {
        let surface = unsafe {
            platform::create_surface(entry, instance, window)
                .expect("failed to create surface!")
        };
        // device对surface的支持在这个类中
        let surface_loader: Surface = ash::extensions::khr::Surface::new(entry, instance);
        
        SurfaceStuff {
            surface: surface,
            surface_loader: surface_loader
        }
    }

    pub fn query_swapchain_support(surface_stuff: &SurfaceStuff, physical_device: &vk::PhysicalDevice) -> SwapChainSupportDetails {
        SwapChainSupportDetails {
            capabilities: unsafe {
                surface_stuff.surface_loader.get_physical_device_surface_capabilities(*physical_device, surface_stuff.surface).expect("failed to load physical device surface capabilities!")
            },
            formats: unsafe {
                surface_stuff.surface_loader.get_physical_device_surface_formats(*physical_device, surface_stuff.surface).expect("failed to load physical device surface formats!")
            },
            present_modes: unsafe {
                surface_stuff.surface_loader.get_physical_device_surface_present_modes(*physical_device, surface_stuff.surface).expect("failed to load physical device surface present modes!")
            }
        }
    }

    pub fn create_swapchain(
        instance: &ash::Instance, surface_stuff: &SurfaceStuff, 
        physical_device: &vk::PhysicalDevice, device: &ash::Device, window: &winit::window::Window) 
        -> SwapChainStuff {
        let queue_family_indices = VulkanRHI::find_queue_family(instance, physical_device, surface_stuff);
        let sharing_mode_checker = queue_family_indices.graphics_family == queue_family_indices.present_family;

        let swapchain_support_details = VulkanRHI::query_swapchain_support(surface_stuff, physical_device);
        println!("Swapchain support from surface & physical_device");
        
        let swap_surface_format = VulkanRHI::choose_swap_surface_format(&swapchain_support_details);
        for format in swapchain_support_details.formats.iter() {
            println!("\t format: {:?}", format);
        }

        let swap_extent = VulkanRHI::choose_swap_extent(&swapchain_support_details, window);
        println!("\t capabilities: {:?}", swapchain_support_details.capabilities);

        let swap_present_mode = VulkanRHI::choose_swap_present_mode(&swapchain_support_details);
        for present_mode in swapchain_support_details.present_modes {
            println!("\t present_mode: {:?}", present_mode);
        }

        let swapchain_create_info = vk::SwapchainCreateInfoKHR {
            s_type: vk::StructureType::SWAPCHAIN_CREATE_INFO_KHR,
            p_next: ptr::null(),
            flags: vk::SwapchainCreateFlagsKHR::empty(),
            surface: surface_stuff.surface,
            min_image_count: swapchain_support_details.capabilities.min_image_count + 1,
            image_format: swap_surface_format.format,
            image_color_space: swap_surface_format.color_space,
            image_extent: swap_extent,
            image_array_layers: 1,
            image_usage: vk::ImageUsageFlags::COLOR_ATTACHMENT,
            image_sharing_mode: match sharing_mode_checker {
                true => vk::SharingMode::EXCLUSIVE,
                false => vk::SharingMode::CONCURRENT
            },
            queue_family_index_count: match sharing_mode_checker {
                true => 0,
                false => 2
            },
            p_queue_family_indices: match sharing_mode_checker {
                true => ptr::null(),
                false => vec![
                    queue_family_indices.graphics_family.unwrap(),
                    queue_family_indices.present_family.unwrap(),
                ].as_ptr()
            },
            pre_transform: swapchain_support_details.capabilities.current_transform,
            composite_alpha: vk::CompositeAlphaFlagsKHR::OPAQUE,
            present_mode: swap_present_mode,
            clipped: vk::TRUE,
            old_swapchain: vk::SwapchainKHR::null()
        };

        // Ash对Swap的API集合
        let swapchain_loader = ash::extensions::khr::Swapchain::new(instance, device);
        // 创建SwapChain
        let swapchain = unsafe {
            swapchain_loader
                .create_swapchain(&swapchain_create_info, None)
                .expect("Failed to create Swapchain!")
        };
        // 有了swapchain就有对应的Images
        let swapchain_images = unsafe {
            swapchain_loader
                .get_swapchain_images(swapchain)
                .expect("Failed to get Swapchain Images.")
        };

        println!("Swapchain Images");
        for swapchain_image in swapchain_images.iter() {
            println!("\t Swapchain image: {:?}", swapchain_image);
        }

        SwapChainStuff {
            swapchain_loader,
            swapchain,
            swapchain_format: swap_surface_format.format,
            swapchain_extent: swap_extent,
            swapchain_images,
        }

    }

    pub fn choose_swap_surface_format(swapchain_support_details: &SwapChainSupportDetails) -> SurfaceFormatKHR {
        let available_formats = &swapchain_support_details.formats;

        for available_format in available_formats.iter() {
            if available_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR && available_format.format == vk::Format::B8G8R8A8_SRGB {
                return available_format.clone();
            }
        }

        available_formats[0]
    }

    pub fn choose_swap_present_mode(swapchain_support_details: &SwapChainSupportDetails) -> PresentModeKHR {
        let available_present_modes = &swapchain_support_details.present_modes;

        for available_present_mode in available_present_modes.iter() {
            if available_present_mode == &vk::PresentModeKHR::MAILBOX {
                return available_present_mode.clone();
            }
        }

        vk::PresentModeKHR::FIFO
    }

    pub fn choose_swap_extent(swapchain_support_details: &SwapChainSupportDetails, _window: &winit::window::Window) -> Extent2D {
        let capabilities = swapchain_support_details.capabilities;

        if capabilities.current_extent.width != u32::MAX {
            capabilities.current_extent
        } else {
            // let size = window.inner_size();
            use num::clamp;

            Extent2D {
                width: clamp(
                    WINDOW_WIDTH as u32,
                    capabilities.min_image_extent.width,
                    capabilities.max_image_extent.width
                ),
                height: clamp(
                    WINDOW_HEIGHT as u32,
                    capabilities.min_image_extent.height,
                    capabilities.max_image_extent.height
                )
            }
        }
    }

    pub fn create_image_views(device: &ash::Device, swapchain_format: &vk::Format ,swapchain_images: &Vec<vk::Image>) -> Vec<ImageView> {
        let mut swapchain_image_views = vec![];

        for swapchain_image in swapchain_images.iter() {
            let image_view = Self::create_image_view(device, swapchain_image, swapchain_format, &vk::ImageAspectFlags::COLOR);
            swapchain_image_views.push(image_view);
        }   

        swapchain_image_views
    }

    pub fn create_graphics_pipeline(device: &ash::Device, render_pass: &vk::RenderPass, swapchain_stuff: &SwapChainStuff, descriptor_set_layouts: &Vec<vk::DescriptorSetLayout>) 
    -> (Vec<vk::Pipeline>, vk::PipelineLayout) {
        let vert_shader_code = VulkanRHI::read_shader_code(Path::new("./vulkan-tutorial-rs/src/shaders/spv/vert.spv"));
        let frag_shader_code = VulkanRHI::read_shader_code(Path::new("./vulkan-tutorial-rs/src/shaders/spv/frag.spv"));

        let vert_shader_module = VulkanRHI::create_shader_module(device, &vert_shader_code);
        let frag_shader_module = VulkanRHI::create_shader_module(device, &frag_shader_code);

        let main_function_name = CString::new("main").unwrap(); 

        // Create Shader Stage
        let vert_shader_stage_create_info = vk::PipelineShaderStageCreateInfo {
            s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineShaderStageCreateFlags::empty(),
            stage: vk::ShaderStageFlags::VERTEX,
            module: vert_shader_module,
            p_name: main_function_name.as_ptr(),
            p_specialization_info: ptr::null() // 教程上提供了这个信息，可以替换Const?
        };
        let frag_shader_stage_create_info = vk::PipelineShaderStageCreateInfo {
            s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineShaderStageCreateFlags::empty(),
            stage: vk::ShaderStageFlags::FRAGMENT,
            module: frag_shader_module,
            p_name: main_function_name.as_ptr(),
            p_specialization_info: ptr::null() // 教程上提供了这个信息，可以替换Const?
        };
        let shader_stages = vec![vert_shader_stage_create_info, frag_shader_stage_create_info];

        // Dynamic State Create Info
        let dynamic_states = vec![vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
        let pipeline_dynamic_state_create_info = vk::PipelineDynamicStateCreateInfo {
            s_type: vk::StructureType::PIPELINE_DYNAMIC_STATE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineDynamicStateCreateFlags::empty(),
            dynamic_state_count: dynamic_states.len() as u32,
            p_dynamic_states: dynamic_states.as_ptr()
        };

        // Vertex Binding Description
        let vertex_binding_description = [vk::VertexInputBindingDescription{
            binding: 0,
            stride: size_of::<Vertex>() as u32,
            input_rate: vk::VertexInputRate::VERTEX
        }];

        // Vertex Attribute Description
        let vertex_attribute_description = [
            vk::VertexInputAttributeDescription {
                location: 0,
                binding: 0,
                format: vk::Format::R32G32B32_SFLOAT,
                offset: offset_of!(Vertex, position) as u32
            },
            vk::VertexInputAttributeDescription {
                location: 1,
                binding: 0,
                format: vk::Format::R32G32B32_SFLOAT,
                offset: offset_of!(Vertex, normal) as u32
            },
            vk::VertexInputAttributeDescription {
                location: 2,
                binding: 0,
                format: vk::Format::R32G32_SFLOAT,
                offset: offset_of!(Vertex, uv) as u32
            },
            vk::VertexInputAttributeDescription {
                location: 3,
                binding: 0,
                format: vk::Format::R32G32B32_SFLOAT,
                offset: offset_of!(Vertex, color) as u32
            },
            vk::VertexInputAttributeDescription {
                location: 4,
                binding: 0,
                format: vk::Format::R16G16B16A16_UINT,
                offset: offset_of!(Vertex, joint_index) as u32
            },
            vk::VertexInputAttributeDescription {
                location: 5,
                binding: 0,
                format: vk::Format::R32G32B32A32_SFLOAT,
                offset: offset_of!(Vertex, joint_weight) as u32
            }
        ];

        // Vertex Input State Create Info
        let pipeline_vertex_input_state_create_info = vk::PipelineVertexInputStateCreateInfo {
            s_type: vk::StructureType::PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineVertexInputStateCreateFlags::empty(),
            vertex_attribute_description_count: vertex_attribute_description.len() as u32,
            vertex_binding_description_count: vertex_binding_description.len() as u32,
            p_vertex_attribute_descriptions: vertex_attribute_description.as_ptr(),
            p_vertex_binding_descriptions: vertex_binding_description.as_ptr()
        };

        // Input Assembly
        let pipeline_input_assembly_state_create_info = vk::PipelineInputAssemblyStateCreateInfo {
            s_type: vk::StructureType::PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineInputAssemblyStateCreateFlags::empty(),
            topology: vk::PrimitiveTopology::TRIANGLE_LIST,
            primitive_restart_enable: vk::FALSE // 图元重启动
        };

        // Viewports and scissors
        let viewport = [vk::Viewport {
            x: 0.0f32,
            y: 0.0f32,
            width: swapchain_stuff.swapchain_extent.width as f32,
            height: swapchain_stuff.swapchain_extent.height as f32,
            min_depth: 0.0f32,
            max_depth: 1.0f32
        }];
        let scissor = [vk::Rect2D {
            offset: Offset2D { x: 0, y: 0 },
            extent: swapchain_stuff.swapchain_extent
        }];
        let pipeline_viewport_state_create_info = vk::PipelineViewportStateCreateInfo {
            s_type: vk::StructureType::PIPELINE_VIEWPORT_STATE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineViewportStateCreateFlags::empty(),
            viewport_count: 1,
            p_viewports: viewport.as_ptr(),
            scissor_count: 1,
            p_scissors: scissor.as_ptr()
        };

        // Rasterizer
        let pipeline_rasterization_state_create_info = vk::PipelineRasterizationStateCreateInfo {
            s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineRasterizationStateCreateFlags::empty(),
            depth_clamp_enable: vk::FALSE,
            rasterizer_discard_enable: vk::FALSE,
            polygon_mode: vk::PolygonMode::FILL,
            cull_mode: vk::CullModeFlags::NONE,
            front_face: vk::FrontFace::CLOCKWISE,
            depth_bias_enable: vk::FALSE,
            depth_bias_constant_factor: 0.0f32,
            depth_bias_clamp: 0.0f32,
            depth_bias_slope_factor: 0.0f32,
            line_width: 1.0f32
        };

        // Multisampling
        let pipeline_multisample_state_create_info = vk::PipelineMultisampleStateCreateInfo {
            s_type: vk::StructureType::PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineMultisampleStateCreateFlags::empty(),
            rasterization_samples: vk::SampleCountFlags::TYPE_1,
            sample_shading_enable: vk::FALSE,
            min_sample_shading: 1.0f32,
            p_sample_mask: ptr::null(),
            alpha_to_coverage_enable: vk::FALSE,
            alpha_to_one_enable: vk::FALSE
        };

        // Color Blending
        let pipeline_color_blend_attachment_state = [vk::PipelineColorBlendAttachmentState {
            color_write_mask: ColorComponentFlags::RGBA,
            blend_enable: vk::FALSE,
            src_color_blend_factor: BlendFactor::ONE,
            dst_color_blend_factor: BlendFactor::ZERO,
            color_blend_op: vk::BlendOp::ADD,
            src_alpha_blend_factor: BlendFactor::ONE,
            dst_alpha_blend_factor: BlendFactor::ZERO,
            alpha_blend_op: vk::BlendOp::ADD
        }];
        let pipeline_color_blend_state_create_info = vk::PipelineColorBlendStateCreateInfo {
            s_type: vk::StructureType::PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineColorBlendStateCreateFlags::empty(),
            logic_op_enable: vk::FALSE,
            logic_op: vk::LogicOp::COPY,
            attachment_count: pipeline_color_blend_attachment_state.len() as u32,
            p_attachments: pipeline_color_blend_attachment_state.as_ptr(),
            blend_constants: [0.0f32, 0.0f32, 0.0f32, 0.0f32]
        };

        let stencil_state = vk::StencilOpState {
            fail_op: vk::StencilOp::KEEP,
            pass_op: vk::StencilOp::KEEP,
            depth_fail_op: vk::StencilOp::KEEP,
            compare_op: vk::CompareOp::ALWAYS,
            compare_mask: 0,
            write_mask: 0,
            reference: 0,
        };
        let pipeline_depth_stencil_state_create_info = vk::PipelineDepthStencilStateCreateInfo {
            s_type: vk::StructureType::PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::PipelineDepthStencilStateCreateFlags::empty(),
            depth_test_enable: vk::TRUE,
            depth_write_enable: vk::TRUE,
            depth_compare_op: vk::CompareOp::LESS,
            depth_bounds_test_enable: vk::FALSE,
            stencil_test_enable: vk::FALSE,
            front: stencil_state,
            back: stencil_state,
            max_depth_bounds: 1.0,
            min_depth_bounds: 0.0,
        };

        // Pipeline Layout
        let pipeline_layout_create_info = vk::PipelineLayoutCreateInfo {
            s_type: vk::StructureType::PIPELINE_LAYOUT_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineLayoutCreateFlags::empty(),
            set_layout_count: descriptor_set_layouts.len() as u32,
            p_set_layouts: descriptor_set_layouts.as_ptr(),
            push_constant_range_count: 0,
            p_push_constant_ranges: ptr::null()
        };
        let pipeline_layout = unsafe {
            device
                .create_pipeline_layout(&pipeline_layout_create_info, None)
                .expect("failed to create pipeline layout")
        };

        // Graphics Pipeline
        let graphics_pipeline_create_infos = [vk::GraphicsPipelineCreateInfo {
            s_type: vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO,
            p_next: ptr::null(),
            flags: PipelineCreateFlags::empty(),
            stage_count: shader_stages.len() as u32,
            p_stages: shader_stages.as_ptr(),
            p_vertex_input_state: &pipeline_vertex_input_state_create_info,
            p_input_assembly_state: &pipeline_input_assembly_state_create_info,
            p_tessellation_state: ptr::null(),
            p_viewport_state: &pipeline_viewport_state_create_info,
            p_rasterization_state: &pipeline_rasterization_state_create_info,
            p_multisample_state: &pipeline_multisample_state_create_info,
            p_depth_stencil_state: &pipeline_depth_stencil_state_create_info,
            p_color_blend_state: &pipeline_color_blend_state_create_info,
            p_dynamic_state: &pipeline_dynamic_state_create_info,
            layout: pipeline_layout,
            render_pass: *render_pass,
            subpass: 0,
            base_pipeline_handle: vk::Pipeline::null(),
            base_pipeline_index: -1
        }];

        let graphics_pipelines = unsafe {
            device
                .create_graphics_pipelines(vk::PipelineCache::null(), &graphics_pipeline_create_infos, None)
                .expect("failed to create graphics pipelines!")
        };

        unsafe {
            device.destroy_shader_module(vert_shader_module, None);
            device.destroy_shader_module(frag_shader_module, None);
        }

        (graphics_pipelines, pipeline_layout)
    }

    pub fn read_shader_code(shader_path: &Path) -> Vec<u8> {
        use std::fs::File;
        use std::io::Read;

        let spv_file = File::open(shader_path)
            .expect(&format!("Failed to find spv file at {:?}", shader_path));
        let bytes_code: Vec<u8> = spv_file.bytes().filter_map(|byte| byte.ok()).collect();

        bytes_code
    }

    pub fn create_shader_module(device: &ash::Device, code: &Vec<u8>) -> ShaderModule {
        let shader_module_create_info = vk::ShaderModuleCreateInfo {
            s_type: vk::StructureType::SHADER_MODULE_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::ShaderModuleCreateFlags::empty(),
            code_size: code.len(),
            p_code: code.as_ptr() as *const u32
        };

        let shader_module = unsafe {
            device  
                .create_shader_module(&shader_module_create_info, None)
                .expect("failed to create shader module!")  
        };

        shader_module
    }

    pub fn create_render_pass(instance: &ash::Instance, physical_device: &vk::PhysicalDevice, device: &ash::Device, swapchain_stuff: &SwapChainStuff) -> vk::RenderPass {
        let color_attachment = [vk::AttachmentDescription {
            format: swapchain_stuff.swapchain_format,
            flags: vk::AttachmentDescriptionFlags::empty(),
            samples: vk::SampleCountFlags::TYPE_1,
            load_op: vk::AttachmentLoadOp::CLEAR,
            store_op: vk::AttachmentStoreOp::STORE,
            stencil_load_op: vk::AttachmentLoadOp::DONT_CARE,
            stencil_store_op: vk::AttachmentStoreOp::DONT_CARE,
            initial_layout: vk::ImageLayout::UNDEFINED,
            final_layout: vk::ImageLayout::PRESENT_SRC_KHR
        }];
        let depth_attachment = [vk::AttachmentDescription {
            format: Self::find_depth_format(instance, physical_device),
            flags: vk::AttachmentDescriptionFlags::empty(),
            samples: vk::SampleCountFlags::TYPE_1,
            load_op: vk::AttachmentLoadOp::CLEAR,
            store_op: vk::AttachmentStoreOp::STORE,
            stencil_load_op: vk::AttachmentLoadOp::DONT_CARE,
            stencil_store_op: vk::AttachmentStoreOp::DONT_CARE,
            initial_layout: vk::ImageLayout::UNDEFINED,
            final_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL
        }];

        // Subpass: 对于后处理来说，适合用
        let color_attachment_ref = [vk::AttachmentReference {
            attachment: 0,
            layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL
        }];
        let depth_attachment_ref = [vk::AttachmentReference {
            attachment: 1,
            layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL
        }];
        let subpass_description = [vk::SubpassDescription {
            flags: vk::SubpassDescriptionFlags::empty(),
            pipeline_bind_point: vk::PipelineBindPoint::GRAPHICS,
            input_attachment_count: 0,
            p_input_attachments: ptr::null(),
            color_attachment_count: color_attachment_ref.len() as u32,
            p_color_attachments: color_attachment_ref.as_ptr(),
            p_resolve_attachments: ptr::null(),
            p_depth_stencil_attachment: depth_attachment_ref.as_ptr(),
            preserve_attachment_count: 0,
            p_preserve_attachments: ptr::null()
        }];

        // dependency
        // let dependency = [vk::SubpassDependency {
        //     src_subpass: vk::SUBPASS_EXTERNAL,
        //     dst_subpass: 0,
        //     src_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS,
        //     dst_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS,
        //     src_access_mask: vk::AccessFlags::empty(),
        //     dst_access_mask: vk::AccessFlags::COLOR_ATTACHMENT_WRITE | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
        //     dependency_flags: vk::DependencyFlags::empty(),
        // }];
        let dependency = [vk::SubpassDependency {
            src_subpass: vk::SUBPASS_EXTERNAL,
            dst_subpass: 0,
            src_stage_mask: vk::PipelineStageFlags::BOTTOM_OF_PIPE,
            dst_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
            src_access_mask: vk::AccessFlags::MEMORY_READ,
            dst_access_mask: vk::AccessFlags::COLOR_ATTACHMENT_WRITE | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
            dependency_flags: vk::DependencyFlags::BY_REGION,
        }];

        // Render Pass
        let attachments = [color_attachment, depth_attachment].concat();
        let render_pass_create_info = vk::RenderPassCreateInfo {
            s_type: vk::StructureType::RENDER_PASS_CREATE_INFO,
            p_next: ptr::null(),
            flags: RenderPassCreateFlags::empty(),
            attachment_count: attachments.len() as u32,
            p_attachments: attachments.as_ptr(),
            subpass_count: subpass_description.len() as u32,
            p_subpasses: subpass_description.as_ptr(),
            dependency_count: dependency.len() as u32,
            p_dependencies: dependency.as_ptr()
        };

        let render_pass = unsafe {
            device
                .create_render_pass(&render_pass_create_info, None)
                .expect("failed to create render pass")
        };

        render_pass
    }

    pub fn create_framebuffers(device: &ash::Device, swapchain_image_views: &Vec<ImageView>, render_pass: &vk::RenderPass, swapchain_stuff: &SwapChainStuff, depth_image_view: &vk::ImageView) -> Vec<Framebuffer> {
        let mut framebuffers = vec![];

        for swapchain_image_view in swapchain_image_views.iter() {
            let attachments = [*swapchain_image_view, *depth_image_view];

            let framebuffer_create_info = vk::FramebufferCreateInfo {
                s_type: vk::StructureType::FRAMEBUFFER_CREATE_INFO,
                p_next: ptr::null(),
                flags: FramebufferCreateFlags::empty(),
                render_pass: *render_pass,
                attachment_count: attachments.len() as u32,
                p_attachments: attachments.as_ptr(),
                width: swapchain_stuff.swapchain_extent.width,
                height: swapchain_stuff.swapchain_extent.height,
                layers: 1
            };

            framebuffers.push(
                unsafe {
                    device
                        .create_framebuffer(&framebuffer_create_info, None)
                        .expect("failed to create framebuffer")
                }
            )
        }

        framebuffers
    }

    pub fn create_command_pool(instance: &ash::Instance, device: &ash::Device, physical_device: &vk::PhysicalDevice, surface_stuff: &SurfaceStuff) -> vk::CommandPool {
        let queue_family_indices = VulkanRHI::find_queue_family(instance, physical_device, surface_stuff);

        let command_pool_create_info = vk::CommandPoolCreateInfo {
            s_type: vk::StructureType::COMMAND_POOL_CREATE_INFO,
            p_next: ptr::null(),
            flags: CommandPoolCreateFlags::RESET_COMMAND_BUFFER,
            queue_family_index: queue_family_indices.graphics_family.unwrap()
        };

        let command_pool = unsafe {
            device
                .create_command_pool(&command_pool_create_info, None)
                .expect("failed to create command pool!")
        };

        command_pool
    }

    pub fn create_command_buffers(device: &ash::Device, command_pool: &vk::CommandPool, command_buffer_count: u32) -> Vec<vk::CommandBuffer> {
        let command_buffers_allocate_info = vk::CommandBufferAllocateInfo {
            s_type: vk::StructureType::COMMAND_BUFFER_ALLOCATE_INFO,
            p_next: ptr::null(),
            command_pool: *command_pool,
            level: vk::CommandBufferLevel::PRIMARY,
            command_buffer_count: command_buffer_count
        };

        let command_buffers = unsafe {
            device
                .allocate_command_buffers(&command_buffers_allocate_info)
                .expect("failed to allocate command buffers")
        };

        command_buffers
    }
    
    pub fn create_sync_objects(device: &ash::Device) -> (Vec<vk::Semaphore>, Vec<vk::Semaphore>, Vec<vk::Fence>) {
        let semaphore_create_info = vk::SemaphoreCreateInfo {
            s_type: vk::StructureType::SEMAPHORE_CREATE_INFO,
            p_next: ptr::null(),
            flags: SemaphoreCreateFlags::empty()
        };
        let fence_create_info = vk::FenceCreateInfo {
            s_type: vk::StructureType::FENCE_CREATE_INFO,
            p_next: ptr::null(),
            flags: FenceCreateFlags::SIGNALED
        };

        let mut image_available_semaphores = vec![];
        let mut render_finished_semaphores = vec![];
        let mut in_flight_fences = vec![];
        for _index in 0..MAX_FRAMES_IN_FLIGHT {
            image_available_semaphores.push(unsafe {
                device
                    .create_semaphore(&semaphore_create_info, None)
                    .expect("failed to create semaphore!")
                }
            );
            render_finished_semaphores.push(unsafe {
                device
                    .create_semaphore(&semaphore_create_info, None)
                    .expect("failed to create semaphore!")
                }
            );
            in_flight_fences.push(unsafe {
                device
                    .create_fence(&fence_create_info, None)
                    .expect("failed to create semaphore!")
                }
            )
        };

        (image_available_semaphores, render_finished_semaphores, in_flight_fences)
    }

    fn create_buffer(instance: &ash::Instance, device: &ash::Device, physical_device: &vk::PhysicalDevice, size: u64, usage: vk::BufferUsageFlags, properties: vk::MemoryPropertyFlags) -> (vk::Buffer, vk::DeviceMemory) {
        // create
        let create_vertex_buffer_info = vk::BufferCreateInfo {
            s_type: vk::StructureType::BUFFER_CREATE_INFO,
            p_next: ptr::null(),
            flags: BufferCreateFlags::empty(),
            size: size,
            usage: usage,
            sharing_mode: vk::SharingMode::EXCLUSIVE,
            queue_family_index_count: 0,
            p_queue_family_indices: ptr::null()
        };
        let vertex_buffer = unsafe {
            device
                .create_buffer(&create_vertex_buffer_info, None)
                .expect("failed to create buffer")
        };
        // require & alloc
        let buffer_memory_requirements = unsafe {
            device
                .get_buffer_memory_requirements(vertex_buffer)
        };
        println!("Buffer Memory Requirements: {:?}", buffer_memory_requirements);
        let memory_allocate_info = vk::MemoryAllocateInfo {
            s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
            p_next: ptr::null(),
            allocation_size: buffer_memory_requirements.size,
            memory_type_index: Self::find_memory_type(instance, physical_device, buffer_memory_requirements.memory_type_bits, properties)
        };
        let vertex_buffer_memory = unsafe {
            device
                .allocate_memory(&memory_allocate_info, None)
                .expect("failed t allocate memory!")
        };
        // bind
        unsafe {
            device
                .bind_buffer_memory(vertex_buffer, vertex_buffer_memory, 0)
                .expect("failed to bind buffer memory")
        }

        (vertex_buffer, vertex_buffer_memory)
    }

    fn find_memory_type(instance: &ash::Instance, physical_device: &vk::PhysicalDevice, type_filter: u32, properties: vk::MemoryPropertyFlags) -> u32 {
        let physical_device_memory_properties = unsafe {
            instance
                .get_physical_device_memory_properties(*physical_device)
        };
        // println!("Physical Device Memory Properties: {:?}", physical_device_memory_properties);
        
        for i in 0..physical_device_memory_properties.memory_type_count as usize {
            if (type_filter & (1 << i) != 0) && (physical_device_memory_properties.memory_types[i].property_flags & properties == properties) {
                return i as u32;
            }
        }

        panic!("failed to find suitable memory type!");
        // 0
    }

    fn begin_single_time_commands(device: &ash::Device, command_pool: &vk::CommandPool) -> vk::CommandBuffer {
        let command_buffer = Self::create_command_buffers(device, command_pool, 1)[0];

        let command_buffer_begin_info = vk::CommandBufferBeginInfo {
            s_type: vk::StructureType::COMMAND_BUFFER_BEGIN_INFO,
            p_next: ptr::null(),
            flags: CommandBufferUsageFlags::ONE_TIME_SUBMIT, // important
            p_inheritance_info: ptr::null()
        };

        unsafe {
            device.begin_command_buffer(command_buffer, &command_buffer_begin_info).expect("failed to begin command buffer!");
        }

        command_buffer
    }

    fn end_single_time_commands(device: &ash::Device, command_pool: &vk::CommandPool, command_buffer: vk::CommandBuffer, queue: &vk::Queue) {
        unsafe {
            device.end_command_buffer(command_buffer).expect("failed to end command buffer!");
        };
        // submit
        let submit_info = [vk::SubmitInfo {
            s_type: vk::StructureType::SUBMIT_INFO,
            command_buffer_count: 1,
            p_command_buffers: &command_buffer,
            ..Default::default()
        }];
        //
        unsafe {
            device.queue_submit(*queue, &submit_info, vk::Fence::null()).expect("failed to submit queue");
            device.queue_wait_idle(*queue).expect("failed to wait queue idle");
            device.free_command_buffers(*command_pool, &[command_buffer]);
        };
    }

    pub fn create_descriptor_set_layout(device: &ash::Device) -> Vec<vk::DescriptorSetLayout> {
        let descriptor_set_layout_bindings_array = [[vk::DescriptorSetLayoutBinding {
                binding: 0,
                descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
                descriptor_count: 1,
                stage_flags: vk::ShaderStageFlags::VERTEX,
                p_immutable_samplers: ptr::null()
            }], 
            [vk::DescriptorSetLayoutBinding {
                binding: 2,
                descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
                descriptor_count: 1,
                stage_flags: vk::ShaderStageFlags::VERTEX,
                p_immutable_samplers: ptr::null()
            }],
            [vk::DescriptorSetLayoutBinding {
                binding: 3,
                descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
                descriptor_count: 1,
                stage_flags: vk::ShaderStageFlags::FRAGMENT,
                p_immutable_samplers: ptr::null()
            }],
            [vk::DescriptorSetLayoutBinding {
                binding: 4,
                descriptor_type: vk::DescriptorType::STORAGE_BUFFER,
                descriptor_count: 1,
                stage_flags: vk::ShaderStageFlags::VERTEX,
                p_immutable_samplers: ptr::null()
            }]
        ];

        // let descriptor_set_layout_create_infos = descriptor_set_layout_bindings_array.map(
        //     |descriptor_set_layout_bindings|
        //         vk::DescriptorSetLayoutCreateInfo {
        //             s_type: vk::StructureType::DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
        //             p_next: ptr::null(),
        //             flags: vk::DescriptorSetLayoutCreateFlags::empty(),
        //             binding_count: descriptor_set_layout_bindings.len() as u32,
        //             p_bindings: descriptor_set_layout_bindings.as_ptr()
        //         }
        // );

        let descriptor_set_layout_create_infos = [
            vk::DescriptorSetLayoutCreateInfo {
                s_type: vk::StructureType::DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
                p_next: ptr::null(),
                flags: vk::DescriptorSetLayoutCreateFlags::empty(),
                binding_count: descriptor_set_layout_bindings_array[0].len() as u32,
                p_bindings: descriptor_set_layout_bindings_array[0].as_ptr()
            },
            vk::DescriptorSetLayoutCreateInfo {
                s_type: vk::StructureType::DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
                p_next: ptr::null(),
                flags: vk::DescriptorSetLayoutCreateFlags::empty(),
                binding_count: descriptor_set_layout_bindings_array[1].len() as u32,
                p_bindings: descriptor_set_layout_bindings_array[1].as_ptr()
            },
            vk::DescriptorSetLayoutCreateInfo {
                s_type: vk::StructureType::DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
                p_next: ptr::null(),
                flags: vk::DescriptorSetLayoutCreateFlags::empty(),
                binding_count: descriptor_set_layout_bindings_array[2].len() as u32,
                p_bindings: descriptor_set_layout_bindings_array[2].as_ptr()
            },
            vk::DescriptorSetLayoutCreateInfo {
                s_type: vk::StructureType::DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
                p_next: ptr::null(),
                flags: vk::DescriptorSetLayoutCreateFlags::empty(),
                binding_count: descriptor_set_layout_bindings_array[3].len() as u32,
                p_bindings: descriptor_set_layout_bindings_array[3].as_ptr()
            },
        ];

        let descriptor_set_layouts = (unsafe {
            [
                device
                    .create_descriptor_set_layout(&descriptor_set_layout_create_infos[0], None)
                    .expect("failed to create desctiptor set layout"),
                device
                    .create_descriptor_set_layout(&descriptor_set_layout_create_infos[1], None)
                    .expect("failed to create desctiptor set layout"),
                device
                    .create_descriptor_set_layout(&descriptor_set_layout_create_infos[2], None)
                    .expect("failed to create desctiptor set layout"),
                device
                    .create_descriptor_set_layout(&descriptor_set_layout_create_infos[3], None)
                    .expect("failed to create desctiptor set layout")
            ]
        }).to_vec();

        descriptor_set_layouts
    }

    pub fn create_descriptor_pool(device: &ash::Device) -> vk::DescriptorPool {
        let descriptor_pool_size = [
            vk::DescriptorPoolSize {
                ty: vk::DescriptorType::UNIFORM_BUFFER,
                descriptor_count: MAX_FRAMES_IN_FLIGHT * 3 * 8
            },
            vk::DescriptorPoolSize {
                ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
                descriptor_count: MAX_FRAMES_IN_FLIGHT * 8
            },  
            vk::DescriptorPoolSize {
                ty: vk::DescriptorType::STORAGE_BUFFER,
                descriptor_count: MAX_FRAMES_IN_FLIGHT * 8
            },
        ];

        let descriptor_pool_create_info = vk::DescriptorPoolCreateInfo {
            s_type: vk::StructureType::DESCRIPTOR_POOL_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::DescriptorPoolCreateFlags::FREE_DESCRIPTOR_SET,
            max_sets: MAX_FRAMES_IN_FLIGHT * 8,
            pool_size_count: descriptor_pool_size.len() as u32,
            p_pool_sizes: descriptor_pool_size.as_ptr()
        };

        let descriptor_pool = unsafe {
            device
                .create_descriptor_pool(&descriptor_pool_create_info, None)
                .expect("failed to create descriptor pool")
        };

        descriptor_pool
    }

    pub fn create_texture_image(instance: &ash::Instance, device: &ash::Device, physical_device: &vk::PhysicalDevice, command_pool: &vk::CommandPool, queue: &vk::Queue) -> (vk::Image, vk::DeviceMemory) {
        let image_raw = image::open("./vulkan-tutorial-rs/assets/texture.jpg").expect("failed to load texture!");
        let (image_width, image_height) = (image_raw.width(), image_raw.height());
        let image = match &image_raw {
            image::DynamicImage::ImageLuma8(_)
            | image::DynamicImage::ImageRgb8(_) => image_raw.to_rgba8().into_raw(),
            image::DynamicImage::ImageLumaA8(_)
            | image::DynamicImage::ImageRgba8(_) 
            | &_ => image_raw.as_bytes().to_vec(),
        };
        let image_size = image.len() as u64;

        let (staging_buffer, staging_buffer_memory) = 
            Self::create_buffer(instance, device, physical_device, image_size, vk::BufferUsageFlags::TRANSFER_SRC, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT);

        unsafe {
            let staging_buffer_mapped = 
                device
                    .map_memory(staging_buffer_memory, 0, image_size, vk::MemoryMapFlags::empty())
                    .expect("failed to map memory!") as *mut u8;
            staging_buffer_mapped.copy_from_nonoverlapping(image.as_ptr(), image_size as usize);
            device
                .unmap_memory(staging_buffer_memory);
        }
        // image
        let (texture_image, texture_image_memory) = Self::create_image(
            instance, device, physical_device, image_width, image_height, 
            vk::Format::R8G8B8A8_SRGB,
            vk::ImageTiling::OPTIMAL,
            vk::ImageUsageFlags::TRANSFER_DST | vk::ImageUsageFlags::SAMPLED,
            vk::MemoryPropertyFlags::DEVICE_LOCAL);

        Self::transition_image_layout(device, command_pool, queue, &vk::Format::R8G8B8A8_SRGB, vk::ImageLayout::UNDEFINED, vk::ImageLayout::TRANSFER_DST_OPTIMAL, &texture_image);
        Self::copy_buffer_to_image(device, command_pool, queue, &staging_buffer, &texture_image, image_width, image_height);
        Self::transition_image_layout(device, command_pool, queue, &vk::Format::R8G8B8A8_SRGB, vk::ImageLayout::TRANSFER_DST_OPTIMAL, vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, &texture_image);

        unsafe {
            device
                .destroy_buffer(staging_buffer, None);
            device
                .free_memory(staging_buffer_memory, None);
        }

        (texture_image, texture_image_memory)
    }

    pub fn create_image(
        instance: &ash::Instance, 
        device: &ash::Device, 
        physical_device: &vk::PhysicalDevice, 
        width: u32, 
        height: u32, 
        format: vk::Format,
        tiling: vk::ImageTiling,
        usage: vk::ImageUsageFlags,
        properties: vk::MemoryPropertyFlags)
        -> (vk::Image, vk::DeviceMemory) {
        let image_create_info = vk::ImageCreateInfo {
            s_type: vk::StructureType::IMAGE_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::ImageCreateFlags::empty(),
            image_type: vk::ImageType::TYPE_2D,
            format: format,
            extent: vk::Extent3D {
                width: width,
                height: height,
                depth: 1
            },
            mip_levels: 1,
            array_layers: 1,
            samples: vk::SampleCountFlags::TYPE_1,
            tiling: tiling,
            usage: usage,
            sharing_mode: vk::SharingMode::EXCLUSIVE,
            queue_family_index_count: 0,
            p_queue_family_indices: ptr::null(),
            initial_layout: vk::ImageLayout::UNDEFINED
        };

        let image = unsafe {
            device
                .create_image(&image_create_info, None)
                .expect("failed to create image")
        };

        let memory_requirements = unsafe {
            device
                .get_image_memory_requirements(image)
        };

        let memory_allocate_info = vk::MemoryAllocateInfo {
            s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
            p_next: ptr::null(),
            allocation_size: memory_requirements.size,
            memory_type_index: Self::find_memory_type(instance, physical_device, memory_requirements.memory_type_bits, properties)
        };

        let image_memory = unsafe {
            device
                .allocate_memory(&memory_allocate_info, None)
                .expect("failed to allocate memory")
        };

        unsafe {
            device
                .bind_image_memory(image, image_memory, 0)
                .expect("failed to bind image memory")
        };

        (image, image_memory)
    }

    fn transition_image_layout(device: &ash::Device, command_pool: &vk::CommandPool, queue: &vk::Queue, format: &vk::Format, old_layout: vk::ImageLayout, new_layout: vk::ImageLayout, image: &vk::Image) {
        let (src_stage, dst_stage, src_access_mask, dst_access_mask) = {
            if old_layout == vk::ImageLayout::UNDEFINED && new_layout == vk::ImageLayout::TRANSFER_DST_OPTIMAL {
                (vk::PipelineStageFlags::TOP_OF_PIPE, vk::PipelineStageFlags::TRANSFER, vk::AccessFlags::empty(), vk::AccessFlags::TRANSFER_WRITE)
            } else if old_layout == vk::ImageLayout::TRANSFER_DST_OPTIMAL && new_layout == vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL {
                (vk::PipelineStageFlags::TRANSFER, vk::PipelineStageFlags::FRAGMENT_SHADER, vk::AccessFlags::TRANSFER_WRITE, vk::AccessFlags::SHADER_READ)
            } else if old_layout == vk::ImageLayout::UNDEFINED && new_layout == vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL {
                (vk::PipelineStageFlags::TOP_OF_PIPE, 
                    vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS, 
                    vk::AccessFlags::empty(), 
                    vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE)
            } else {
                panic!("failed to transition image layout")
            }
        };

        let command_buffer = Self::begin_single_time_commands(device, command_pool);

        let image_memory_barrier = vk::ImageMemoryBarrier {
            s_type: vk::StructureType::IMAGE_MEMORY_BARRIER,
            p_next: ptr::null(),
            src_access_mask: src_access_mask,
            dst_access_mask: dst_access_mask,
            old_layout: old_layout,
            new_layout: new_layout,
            src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
            dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
            image: *image,
            subresource_range: vk::ImageSubresourceRange {
                aspect_mask: match new_layout {
                    vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL => {
                        let mut result = vk::ImageAspectFlags::DEPTH;
                        if Self::has_stencil_component(format) {
                            result |= vk::ImageAspectFlags::STENCIL;
                        }
                        result
                    },
                    _ => vk::ImageAspectFlags::COLOR
                },
                base_mip_level: 0,
                level_count: 1,
                base_array_layer: 0,
                layer_count: 1
            }
        };

        unsafe {
            device
                .cmd_pipeline_barrier(
                    command_buffer, 
                    src_stage, 
                    dst_stage, 
                    vk::DependencyFlags::empty(), 
                    &[], 
                    &[], 
                    &[image_memory_barrier])
        }

        Self::end_single_time_commands(device, command_pool, command_buffer, queue)
    }

    fn copy_buffer_to_image(device: &ash::Device, command_pool: &vk::CommandPool, queue: &vk::Queue, src_buffer: &vk::Buffer, dst_image: &vk::Image, width: u32, height: u32) {
        let command_buffer = Self::begin_single_time_commands(device, command_pool);

        let buffer_image_copy = vk::BufferImageCopy {
            buffer_offset: 0,
            buffer_row_length: 0,
            buffer_image_height: 0,

            image_subresource: vk::ImageSubresourceLayers{
                aspect_mask: vk::ImageAspectFlags::COLOR,
                mip_level: 0,
                base_array_layer: 0,
                layer_count: 1
            },

            image_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
            image_extent: vk::Extent3D { width: width, height: height, depth: 1 }
        };

        unsafe {
            device
                .cmd_copy_buffer_to_image(command_buffer, *src_buffer, *dst_image, vk::ImageLayout::TRANSFER_DST_OPTIMAL, &[buffer_image_copy])
        };

        Self::end_single_time_commands(device, command_pool, command_buffer, queue)
    }

    pub fn create_texture_image_view(device: &ash::Device, image: &vk::Image) -> vk::ImageView {
        let image_view = Self::create_image_view(device, image, &vk::Format::R8G8B8A8_SRGB, &vk::ImageAspectFlags::COLOR);
        image_view
    }

    fn create_image_view(device: &ash::Device, image: &vk::Image, format: &vk::Format, aspect_mask: &vk::ImageAspectFlags) -> vk::ImageView {
        let image_views_create_info = vk::ImageViewCreateInfo {
            s_type: vk::StructureType::IMAGE_VIEW_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::ImageViewCreateFlags::empty(),
            image: *image,
            view_type: vk::ImageViewType::TYPE_2D,
            format: *format,
            components: vk::ComponentMapping { 
                r: vk::ComponentSwizzle::IDENTITY, g: vk::ComponentSwizzle::IDENTITY, 
                b: vk::ComponentSwizzle::IDENTITY, a: vk::ComponentSwizzle::IDENTITY 
            },
            subresource_range: ImageSubresourceRange{
                aspect_mask: *aspect_mask,
                base_mip_level: 0,
                level_count: 1,
                base_array_layer: 0,
                layer_count: 1
            }
        };

        unsafe {
            device
                .create_image_view(&image_views_create_info, None)
                .expect("failed to create image view")
        }
    }

    pub fn create_texture_sampler(instance: &ash::Instance, physical_device: &vk::PhysicalDevice, device: &ash::Device) -> vk::Sampler {
        let sampler_create_info = vk::SamplerCreateInfo {
            s_type: vk::StructureType::SAMPLER_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::SamplerCreateFlags::empty(),
            mag_filter: vk::Filter::LINEAR,
            min_filter: vk::Filter::LINEAR,
            mipmap_mode: vk::SamplerMipmapMode::LINEAR,

            address_mode_u: vk::SamplerAddressMode::REPEAT,
            address_mode_v: vk::SamplerAddressMode::REPEAT,
            address_mode_w: vk::SamplerAddressMode::REPEAT,

            mip_lod_bias: 0.0f32,
            anisotropy_enable: vk::TRUE,
            max_anisotropy: unsafe {
                instance.get_physical_device_properties(*physical_device)
            }.limits.max_sampler_anisotropy,
            
            compare_enable: vk::FALSE,
            compare_op: vk::CompareOp::ALWAYS,
            min_lod: 0.0f32,
            max_lod: 0.0f32,
            border_color: vk::BorderColor::INT_OPAQUE_BLACK,
            unnormalized_coordinates: vk::FALSE
        };

        unsafe {
            device
                .create_sampler(&sampler_create_info, None)
                .expect("failed to create sampler")
        }
    }

    pub fn create_depth_resources(instance: &ash::Instance, device: &ash::Device, physical_device: &vk::PhysicalDevice, swapchain_stuff: &SwapChainStuff, command_pool: &vk::CommandPool, queue: &vk::Queue) 
    -> (vk::Image, vk::DeviceMemory, vk::ImageView) {
        let depth_format = Self::find_depth_format(instance, physical_device);
        println!("depth_format : {:?}", depth_format);
        
        let (depth_image, depth_image_memory) = 
            Self::create_image(
                instance, device, physical_device, 
                swapchain_stuff.swapchain_extent.width, swapchain_stuff.swapchain_extent.height, 
                depth_format, vk::ImageTiling::OPTIMAL, vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT, vk::MemoryPropertyFlags::DEVICE_LOCAL);
        let depth_image_view =
            Self::create_image_view(device, &depth_image, &depth_format, &vk::ImageAspectFlags::DEPTH);
        
        Self::transition_image_layout(device, command_pool, queue, &depth_format, vk::ImageLayout::UNDEFINED, vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &depth_image);
        
        (depth_image, depth_image_memory, depth_image_view)
    }

    fn has_stencil_component(format: &vk::Format) -> bool {
        format == &vk::Format::D32_SFLOAT_S8_UINT || format == &vk::Format::D24_UNORM_S8_UINT
    }

    fn find_depth_format(instance: &ash::Instance, physical_device: &vk::PhysicalDevice) -> vk::Format {
        Self::find_supported_format(instance, physical_device, 
            &vec![vk::Format::D32_SFLOAT, vk::Format::D32_SFLOAT_S8_UINT, vk::Format:: D24_UNORM_S8_UINT], 
            &vk::ImageTiling::OPTIMAL, 
            &vk::FormatFeatureFlags::DEPTH_STENCIL_ATTACHMENT)
    }

    fn find_supported_format(instance: &ash::Instance, physical_device: &vk::PhysicalDevice, candidates: &Vec<vk::Format>, tiling: &vk::ImageTiling, features: &vk::FormatFeatureFlags) -> vk::Format {
        for candidate in candidates.iter() {
            let props = unsafe {
                instance
                    .get_physical_device_format_properties(*physical_device, *candidate)
            };

            if tiling == &vk::ImageTiling::LINEAR && (props.linear_tiling_features & *features) == *features {
                return candidate.clone();
            } else if tiling == &vk::ImageTiling::OPTIMAL && (props.optimal_tiling_features & *features) == *features {
                return candidate.clone();
            }
        }

        panic!("failed to find supported format!")
    }

    fn create_buffer_v2<T>(&self, size: u64, usage: vk::BufferUsageFlags, sharing_mode: vk::SharingMode, properties: vk::MemoryPropertyFlags, data: Option<Vec<T>>) 
    -> (vk::Buffer, vk::DeviceMemory) 
    where T: Sized{
        // Create Buffer
        let buffer = unsafe {
            self.logic_device.create_buffer(
                &vk::BufferCreateInfo{
                    s_type: vk::StructureType::BUFFER_CREATE_INFO,
                    p_next: ptr::null(),
                    flags: vk::BufferCreateFlags::empty(),
                    size: size,
                    usage: usage,
                    sharing_mode: sharing_mode,
                    queue_family_index_count: 0,
                    p_queue_family_indices: ptr::null()
                },
                None
            ).expect("[VulkanRHI] create_buffer_v2 Failed to Create Buffer")
        };
        // Require
        let memory_require = unsafe{
            self.logic_device.get_buffer_memory_requirements(buffer)
        };
        // Alloc
        let device_memory = unsafe {
            self.logic_device.allocate_memory(
                &ash::vk::MemoryAllocateInfo{
                    s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
                    p_next: ptr::null(),
                    allocation_size: memory_require.size,
                    memory_type_index: Self::find_memory_type(&self.instance, &self.physical_device, memory_require.memory_type_bits, properties)
                }, 
                None
            ).expect("[VulkanRHI] create_buffer_v2 Failed to Allocate Memory")
        };
        // Bind
        unsafe {
            self.logic_device
                .bind_buffer_memory(buffer, device_memory, 0)
                .expect("[VulkanRHI] Failed to Bind Buffer&Memory")
        }
        // Fill this Memory
        if let Some(cpu_data) = data { unsafe {
            // map，提供一个Cpu可用的Memory句柄
            let host_memory_handle =
                self.logic_device
                    .map_memory(device_memory, 0, size, vk::MemoryMapFlags::empty())
                    .expect("failed to map memory") as *mut T;
            // trans
            host_memory_handle.copy_from_nonoverlapping(cpu_data.as_ptr() as *const T, cpu_data.len());
            // unmap
            self.logic_device
                .unmap_memory(device_memory);
        }};
        // Return
        (buffer, device_memory)
    }

    pub fn create_buffer_usage_v2<T>(&self, size: u64, usage: vk::BufferUsageFlags, data: Option<Vec<T>>) 
        -> GpuBuffer 
        where T: Sized{
        // Create Stage Buffer
        let (stage_buffer, stage_device_memory) = 
            self.create_buffer_v2(
                size, 
                vk::BufferUsageFlags::TRANSFER_SRC, 
                vk::SharingMode::EXCLUSIVE, 
                vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE, 
                data);
        // Create GpuOnly Buffer
        let (buffer, device_memory) = 
            self.create_buffer_v2::<T>(
                size, 
                vk::BufferUsageFlags::TRANSFER_DST | usage, 
                vk::SharingMode::EXCLUSIVE, 
                vk::MemoryPropertyFlags::DEVICE_LOCAL, None);
        // Copy
        self.transfer_buffer_v2(stage_buffer, buffer, size);
        // Destroy Stage Buffer
        unsafe {
            self.logic_device.destroy_buffer(stage_buffer, None);
            self.logic_device.free_memory(stage_device_memory, None);
        }
        // Return
        GpuBuffer{buffer: buffer, memory: device_memory}
    }

    fn transfer_buffer_v2(&self, src_buffer: vk::Buffer, dst_buffer: vk::Buffer, buffer_size: u64) {        
        let command_buffer = Self::begin_single_time_commands(&self.logic_device, &self.command_pool);

        let buffer_copy = [vk::BufferCopy {
            src_offset: 0,
            dst_offset: 0,
            size: buffer_size
        }];

        unsafe {
            self.logic_device.cmd_copy_buffer(command_buffer, src_buffer, dst_buffer, &buffer_copy);
        };

        Self::end_single_time_commands(&self.logic_device, &self.command_pool, command_buffer, &self.graphics_queue);
    }

    pub fn create_texture_from_buffer_v2(&self, image_data: &Vec<u8>, image_width: u32, image_height: u32, queue: &vk::Queue) -> Texture {
        let image_size = image_data.len() as u64;

        let (staging_buffer, staging_buffer_memory) = 
            Self::create_buffer(&self.instance, &self.logic_device, &self.physical_device, image_size, vk::BufferUsageFlags::TRANSFER_SRC, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT);

        unsafe {
            let staging_buffer_mapped = 
                self.logic_device
                    .map_memory(staging_buffer_memory, 0, image_size, vk::MemoryMapFlags::empty())
                    .expect("failed to map memory!") as *mut u8;
            staging_buffer_mapped.copy_from_nonoverlapping(image_data.as_ptr(), image_size as usize);
            self.logic_device
                .unmap_memory(staging_buffer_memory);
        }
        // image
        let (texture_image, texture_image_memory) = Self::create_image(
            &self.instance, &self.logic_device, &self.physical_device, image_width, image_height, 
            vk::Format::R8G8B8A8_SRGB,
            vk::ImageTiling::OPTIMAL,
            vk::ImageUsageFlags::TRANSFER_DST | vk::ImageUsageFlags::SAMPLED,
            vk::MemoryPropertyFlags::DEVICE_LOCAL);

        Self::transition_image_layout(&self.logic_device, &self.command_pool, queue, &vk::Format::R8G8B8A8_SRGB, vk::ImageLayout::UNDEFINED, vk::ImageLayout::TRANSFER_DST_OPTIMAL, &texture_image);
        Self::copy_buffer_to_image(&self.logic_device, &self.command_pool, queue, &staging_buffer, &texture_image, image_width, image_height);
        Self::transition_image_layout(&self.logic_device, &self.command_pool, queue, &vk::Format::R8G8B8A8_SRGB, vk::ImageLayout::TRANSFER_DST_OPTIMAL, vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, &texture_image);

        unsafe {
            self.logic_device
                .destroy_buffer(staging_buffer, None);
            self.logic_device
                .free_memory(staging_buffer_memory, None);
        }

        let image_view = Self::create_image_view(&self.logic_device, &texture_image, &vk::Format::R8G8B8A8_SRGB, &vk::ImageAspectFlags::COLOR);

        let sampler_create_info = vk::SamplerCreateInfo {
            s_type: vk::StructureType::SAMPLER_CREATE_INFO,
            p_next: ptr::null(),
            flags: vk::SamplerCreateFlags::empty(),
            mag_filter: vk::Filter::LINEAR,
            min_filter: vk::Filter::LINEAR,
            mipmap_mode: vk::SamplerMipmapMode::LINEAR,

            address_mode_u: vk::SamplerAddressMode::REPEAT,
            address_mode_v: vk::SamplerAddressMode::REPEAT,
            address_mode_w: vk::SamplerAddressMode::REPEAT,

            mip_lod_bias: 0.0f32,
            anisotropy_enable: vk::TRUE,
            max_anisotropy: unsafe {
                self.instance.get_physical_device_properties(self.physical_device)
            }.limits.max_sampler_anisotropy,
            
            compare_enable: vk::FALSE,
            compare_op: vk::CompareOp::ALWAYS,
            min_lod: 0.0f32,
            max_lod: 0.0f32,
            border_color: vk::BorderColor::INT_OPAQUE_BLACK,
            unnormalized_coordinates: vk::FALSE
        };

        let image_sampler = unsafe {
            self.logic_device
                .create_sampler(&sampler_create_info, None)
                .expect("failed to create sampler")
        };

        Texture{
            image: texture_image,
            device_memory: texture_image_memory,
            image_view: image_view,
            sampler: image_sampler
        }
    }
    
    pub fn create_uniform_buffers_v2<T>(&self, buffer_count: u32, buffer_size: u64) -> UniformBuffer<T> {
        let mut uniform_buffers = vec![];
        let mut uniform_buffers_memory = vec![];
        let mut uniform_buffers_mapped = vec![];

        for _index in 0..buffer_count {
            let (buffer, device_buffer) = 
                Self::create_buffer(&self.instance, &self.logic_device, &self.physical_device, buffer_size, vk::BufferUsageFlags::UNIFORM_BUFFER, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT);
            let buffer_mapped = unsafe {
                self.logic_device
                    .map_memory(device_buffer, 0, buffer_size, vk::MemoryMapFlags::empty())
                    .expect("failed to map memory!") as *mut T
            };
            uniform_buffers.push(buffer);
            uniform_buffers_memory.push(device_buffer);
            uniform_buffers_mapped.push(buffer_mapped);
        }

        UniformBuffer {buffer: uniform_buffers, device_memory: uniform_buffers_memory, mapped_handle: uniform_buffers_mapped}
    }

    pub fn create_skin_buffers_v2(&self, buffer_count: u32, buffer_size: u64) -> SkinSSBO {
        let mut uniform_buffers = vec![];
        let mut uniform_buffers_memory = vec![];
        let mut uniform_buffers_mapped = vec![];

        for _index in 0..buffer_count {
            let (buffer, device_buffer) = 
                Self::create_buffer(
                    &self.instance, 
                    &self.logic_device, &self.physical_device, buffer_size, 
                    vk::BufferUsageFlags::STORAGE_BUFFER, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT);
            let buffer_mapped = unsafe {
                self.logic_device
                    .map_memory(device_buffer, 0, buffer_size, vk::MemoryMapFlags::empty())
                    .expect("failed to map memory!") as *mut [[f32; 4]; 4]
            };
            uniform_buffers.push(buffer);
            uniform_buffers_memory.push(device_buffer);
            uniform_buffers_mapped.push(buffer_mapped);
        }

        SkinSSBO {buffer: uniform_buffers, device_memory: uniform_buffers_memory, mapped_handle: uniform_buffers_mapped}
    }

    pub fn create_descriptor_set_frame(&self, uniform_buffers: &Vec<vk::Buffer>) -> Vec<Vec<vk::DescriptorSet>> {
        let descriptor_set_allocate_info = vk::DescriptorSetAllocateInfo {
            s_type: vk::StructureType::DESCRIPTOR_SET_ALLOCATE_INFO,
            p_next: ptr::null(),
            descriptor_pool: self.descriptor_pool,
            descriptor_set_count: 1,
            p_set_layouts : [
                self.descriptor_set_layouts[DescriptorType::PerFrame as usize], 
            ].as_ptr()
        };

        let mut output_descriptor_sets = vec![];

        for index in 0..MAX_FRAMES_IN_FLIGHT as usize {
            let mut write_descriptor_sets = vec![];

            let descriptor_sets: Vec<vk::DescriptorSet> = unsafe {
                self.logic_device
                    .allocate_descriptor_sets(&descriptor_set_allocate_info)
                    .expect("failed to allocate descriptor sets!")
            };

            let descriptor_buffer_info = vk::DescriptorBufferInfo {
                buffer: uniform_buffers[index],
                offset: 0,
                range: size_of::<PerFrameUniformData>() as u64
            };

            let write_desciptor_set = vk::WriteDescriptorSet {
                s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
                p_next: ptr::null(),
                dst_set: descriptor_sets[0],
                dst_binding: 0,
                dst_array_element: 0,
                descriptor_count: 1,
                descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
                p_buffer_info: &descriptor_buffer_info,
                p_image_info: ptr::null(),
                p_texel_buffer_view: ptr::null()
            };
            write_descriptor_sets.push(write_desciptor_set);

            unsafe {
                self.logic_device
                    .update_descriptor_sets(&write_descriptor_sets, &[])
            }

            output_descriptor_sets.push(descriptor_sets);
        }

        output_descriptor_sets

    }

    pub fn create_descriptor_set_v2(
        &self, 
        uniform_buffers: &Vec<vk::Buffer>, texture_image_sampler: &vk::Sampler, texture_image_view: &vk::ImageView, 
        stroage_buffer: Option<&SkinSSBO>, storage_buffer_size: u64) -> Vec<Vec<vk::DescriptorSet>> {
        let descriptor_set_allocate_info = vk::DescriptorSetAllocateInfo {
            s_type: vk::StructureType::DESCRIPTOR_SET_ALLOCATE_INFO,
            p_next: ptr::null(),
            descriptor_pool: self.descriptor_pool,
            descriptor_set_count: 3,
            p_set_layouts : [
                self.descriptor_set_layouts[DescriptorType::PerDrawcall as usize], 
                self.descriptor_set_layouts[DescriptorType::PerMaterial as usize],
                self.descriptor_set_layouts[DescriptorType::PerDrawcallPerMesh as usize]
            ].as_ptr()
        };

        let mut output_descriptor_sets = vec![];

        for index in 0..MAX_FRAMES_IN_FLIGHT as usize {
            let mut write_descriptor_sets = vec![];

            let descriptor_sets = unsafe {
                self.logic_device
                    .allocate_descriptor_sets(&descriptor_set_allocate_info)
                    .expect("failed to allocate descriptor sets!")
            };
            println!("[Vulkan RHI] descriptor_sets size({})", descriptor_sets.len());

            let descriptor_buffer_info = vk::DescriptorBufferInfo {
                buffer: uniform_buffers[index],
                offset: 0,
                range: size_of::<PerObjectUniformData>() as u64
            };

            let write_desciptor_set = vk::WriteDescriptorSet {
                s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
                p_next: ptr::null(),
                dst_set: descriptor_sets[0],
                dst_binding: 2,
                dst_array_element: 0,
                descriptor_count: 1,
                descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
                p_buffer_info: &descriptor_buffer_info,
                p_image_info: ptr::null(),
                p_texel_buffer_view: ptr::null()
            };
            write_descriptor_sets.push(write_desciptor_set);

            let descriptor_buffer_info4 = vk::DescriptorImageInfo {
                sampler: *texture_image_sampler,
                image_view: *texture_image_view,
                image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL
            };

            let write_desciptor_set4 = vk::WriteDescriptorSet {
                s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
                p_next: ptr::null(),
                dst_set: descriptor_sets[1],
                dst_binding: 3,
                dst_array_element: 0,
                descriptor_count: 1,
                descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
                p_buffer_info: ptr::null(),
                p_image_info: &descriptor_buffer_info4,
                p_texel_buffer_view: ptr::null()
            };
            write_descriptor_sets.push(write_desciptor_set4);

            if let Some(stroage_buffer) = stroage_buffer {
                let descriptor_buffer_info5 = vk::DescriptorBufferInfo {
                    buffer: stroage_buffer.buffer[index],
                    offset: 0,
                    range: storage_buffer_size
                };
                let write_descriptor_set5 = vk::WriteDescriptorSet {
                    s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
                    p_next: ptr::null(),
                    dst_set: descriptor_sets[2],
                    dst_binding: 4,
                    dst_array_element: 0,
                    descriptor_count: 1,
                    descriptor_type: vk::DescriptorType::STORAGE_BUFFER,
                    p_buffer_info: &descriptor_buffer_info5,
                    p_image_info: ptr::null(),
                    p_texel_buffer_view: ptr::null()
                };
                write_descriptor_sets.push(write_descriptor_set5);
    
            } else {
                let descriptor_buffer_info5 = vk::DescriptorBufferInfo {
                    buffer: self.null_stroage_buffer,
                    offset: 0,
                    range: 0
                };
                let write_descriptor_set5 = vk::WriteDescriptorSet {
                    s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
                    p_next: ptr::null(),
                    dst_set: descriptor_sets[2],
                    dst_binding: 4,
                    dst_array_element: 0,
                    descriptor_count: 1,
                    descriptor_type: vk::DescriptorType::STORAGE_BUFFER,
                    p_buffer_info: &descriptor_buffer_info5,
                    p_image_info: ptr::null(),
                    p_texel_buffer_view: ptr::null()
                };
                write_descriptor_sets.push(write_descriptor_set5);
            }

            unsafe {
                self.logic_device
                    .update_descriptor_sets(&write_descriptor_sets, &[])
            }
            output_descriptor_sets.push(descriptor_sets);
        }

        output_descriptor_sets
    }
}